package com.app114.app.android.rk;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.cordova.CordovaWebView;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.IPlugin;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.ShareCompat;
import android.util.Log;
import android.util.Patterns;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Display;
import android.view.MenuInflater;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.DownloadListener;
import android.webkit.GeolocationPermissions.Callback;
import android.webkit.URLUtil;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.app114.app.android.rk.conf.Conf;
import com.app114.app.android.rk.log.Logger;
import com.app114.app.android.rk.utils.DataFactory;
import com.app114.app.android.rk.utils.DeviceUtil;
import com.app114.app.android.rk.utils.FileUtil;
import com.app114.app.android.rk.webkit.WebviewUtils;
import com.app114.app.android.rk.widget.RayMenu;
import com.umeng.api.sns.UMSnsService;

public class Browser extends BaseFragmentActivity implements CordovaInterface, DownloadListener, OnNavigationListener,
		View.OnCreateContextMenuListener {

	private static final String LOCAL_INDEX = "file:///android_asset/index.html";
	private static final String LOCAL_ERROR = "file:///android_asset/error.html";
	private static final int GONE = View.GONE;
	private static final int VISIBLE = View.VISIBLE;

	protected static final String TAG = Browser.class.getName();

	private static final int[] ITEM_DRAWABLES = { R.drawable.ic_browser_tool_share_selector,
			R.drawable.ic_browser_tool_reload_selector, R.drawable.ic_browser_tool_fullscreen_selector };

	private String mQuickSearch_Current = DataFactory.SE_ITEM[0];
	private final static String GOOGLE_SEARCH_SOURCE_SUGGEST = "browser-suggest";
	private final static String GOOGLE_SEARCH_SOURCE_UNKNOWN = "unknown";
	private final static String QUERY_PLACE_HOLDER = "%s";

	private boolean mIsActionbarShow = true;
	private int mErrorCode = -1;
	private ProgressBar mProgressBar;
	private CordovaWebView mWebview;

	private RayMenu mRayMenu;
	protected String mTitle;
	private String v2c_file_path;

	private ActionBar mActionBar;

	@Override
	public void cancelLoadUrl() {
		// TODO Auto-generated method stub

	}

	@Override
	public Activity getActivity() {
		return this;
	}

	@Override
	public Context getContext() {
		return this;
	}

	/**
	 * Called when a message is sent to plugin.
	 * 
	 * @param id
	 *            The message id
	 * @param data
	 *            The message data
	 * @return Object or null
	 */
	@Override
	public Object onMessage(String id, Object data) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setActivityResultCallback(IPlugin arg0) {
		// TODO Auto-generated method stub
	}

	/**
	 * Launch an activity for which you would like a result when it finished. When this activity exits, your onActivityResult()
	 * method will be called.
	 * 
	 * @param command
	 *            The command object
	 * @param intent
	 *            The intent to start
	 * @param requestCode
	 *            The request code that is passed to callback to identify the activity
	 */
	@Override
	public void startActivityForResult(IPlugin command, Intent intent, int requestCode) {
		// TODO Auto-generated method stub
		super.startActivityForResult(intent, requestCode);
	}

	@Override
	protected void activitySetup(Bundle savedInstanceState) {

		Intent intent = getIntent();
		String url = "";
		if (intent != null) {
			url = getUrlFromIntent(intent, url);
		}

		v2c_file_path = FileUtil.getV2cFilePath() + File.separator;

		final String webName = intent.getStringExtra(Conf.KEY_WEB_NAME);
		setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
		mActionBar = getSupportActionBar();
		mActionBar.setTitle("正在加载 " + webName);

		mActionBar.setDisplayShowTitleEnabled(true);
		mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
		Context context = mActionBar.getThemedContext();
		ArrayAdapter<CharSequence> list = ArrayAdapter.createFromResource(context, R.array.se_item,
				R.layout.sherlock_spinner_item);
		list.setDropDownViewResource(R.layout.sherlock_spinner_dropdown_item);
		mActionBar.setListNavigationCallbacks(list, this);

		setContentView(R.layout.activity_browser);
		mWebview = (CordovaWebView) findViewById(R.id.tutorialView);
		WebviewUtils.simpleSettings(mWebview);
		mWebview.setOnCreateContextMenuListener(this);
		mProgressBar = (ProgressBar) findViewById(R.id.progressBar);

		mWebview.setWebChromeClient(new WebChromeClient() {

			@Override
			public void onProgressChanged(WebView view, int newProgress) {
				mProgressBar.setProgress(newProgress);
				if (newProgress == 100) {
					mActionBar.setTitle(mTitle != null && mTitle.equals("") ? webName : mTitle);
				}
			}

			@Override
			public void onGeolocationPermissionsShowPrompt(final String origin, final Callback callback) {
				final boolean remember = false;
				AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
				builder.setTitle("Locations");
				builder.setMessage("Would like to use your Current Location ").setCancelable(true)
						.setPositiveButton("Allow", new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {
								callback.invoke(origin, true, remember);
							}
						}).setNegativeButton("Don't Allow", new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {
								// origin, allow, remember
								callback.invoke(origin, false, remember);
							}
						});
				AlertDialog alert = builder.create();
				alert.show();
			}

			@Override
			public void onReceivedTitle(WebView view, String title) {
				super.onReceivedTitle(view, title);
				mTitle = title;
			}
		});
		mWebview.setWebViewClient(new WebViewClient() {

			@Override
			public void onPageFinished(WebView view, String url) {
				mProgressBar.setVisibility(GONE);
				super.onPageFinished(view, url);
			}

			@Override
			public void onPageStarted(WebView view, String url, Bitmap favicon) {
				mProgressBar.setVisibility(VISIBLE);
				super.onPageStarted(view, url, favicon);
			}

			@Override
			public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
				super.onReceivedError(view, errorCode, description, failingUrl);
				// mQuickSearch_Current = LOCAL_ERROR;
				// DeviceUtil.toast(mContext, "errorCode-->" + errorCode + ", description-->" + description) ;
				mErrorCode = errorCode;
				mWebview.loadUrl(LOCAL_ERROR);
			}

			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {
				String endUrl = url.substring(url.lastIndexOf("."));
				if (endUrl.startsWith(".3gp") || endUrl.startsWith(".mp4") || endUrl.startsWith(".webm")
						|| endUrl.startsWith(".ogv") || endUrl.startsWith(".fsxs")) {
					Uri uri = Uri.parse(url);
					Intent intent = new Intent(Intent.ACTION_VIEW, uri);
					intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
					intent.setType("video/*");
					intent.setDataAndType(uri, "video/*");
					startActivity(intent);
				} else {
					view.loadUrl(url);
				}

				return true;
			}

		});

		mWebview.setDownloadListener(this);
		url = url.equals("") ? LOCAL_INDEX : url;
		mWebview.loadUrl(url);

		mRayMenu = (RayMenu) findViewById(R.id.ray_menu);
		final int itemCount = ITEM_DRAWABLES.length;
		for (int i = 0; i < itemCount; i++) {
			ImageView item = new ImageView(this);
			item.setImageResource(ITEM_DRAWABLES[i]);

			final int position = i;
			mRayMenu.addItem(item, new OnClickListener() {

				@Override
				public void onClick(View v) {
					switch (position) {
					// case 0:
					// Toast.makeText(mContext, "该功能开发中", 1).show();
					// break;
					case 0:
						try {
							share(shot());
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						break;
					case 1:
						mWebview.reload();
						break;
					case 2:
						actionBarShow();
						break;

					default:
						break;
					}
				}
			});// Add a menu item
		}
	}

	@Override
	protected void onNewIntent(Intent intent) {
		super.onNewIntent(intent);
		String url = "";
		url = getUrlFromIntent(intent, url);
		if (mWebview != null) {
			mWebview.loadUrl(url);
		}
	}

	private String getUrlFromIntent(Intent intent, String url) {
		String action = intent.getAction();
		if (action.equals(Intent.ACTION_VIEW)) {
			url = smartUrlFilter(intent.getData());
		} else if (Intent.ACTION_SEARCH.equals(action) || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
				|| Intent.ACTION_WEB_SEARCH.equals(action)) {
			url = intent.getStringExtra(SearchManager.QUERY);
			if (url != null) {
				// In general, we shouldn't modify URL from Intent.
				// But currently, we get the user-typed URL from search box as well.
				url = fixUrl(url);
				url = smartUrlFilter(url);
			}
		}
		return url;
	}

	static String fixUrl(String inUrl) {
		int colon = inUrl.indexOf(':');
		boolean allLower = true;
		for (int index = 0; index < colon; index++) {
			char ch = inUrl.charAt(index);
			if (!Character.isLetter(ch)) {
				break;
			}
			allLower &= Character.isLowerCase(ch);
			if (index == colon - 1 && !allLower) {
				inUrl = inUrl.substring(0, colon).toLowerCase() + inUrl.substring(colon);
			}
		}
		if (inUrl.startsWith("http://") || inUrl.startsWith("https://"))
			return inUrl;
		if (inUrl.startsWith("http:") || inUrl.startsWith("https:")) {
			if (inUrl.startsWith("http:/") || inUrl.startsWith("https:/")) {
				inUrl = inUrl.replaceFirst("/", "//");
			} else
				inUrl = inUrl.replaceFirst(":", "://");
		}
		return inUrl;
	}

	private String smartUrlFilter(Uri inUri) {
		if (inUri != null) {
			return smartUrlFilter(inUri.toString());
		}
		return null;
	}

	private String smartUrlFilter(String url) {

		String inUrl = url.trim();
		boolean hasSpace = inUrl.indexOf(' ') != -1;

		Matcher matcher = ACCEPTED_URI_SCHEMA.matcher(inUrl);
		if (matcher.matches()) {
			// force scheme to lowercase
			String scheme = matcher.group(1);
			String lcScheme = scheme.toLowerCase();
			if (!lcScheme.equals(scheme)) {
				inUrl = lcScheme + matcher.group(2);
			}
			if (hasSpace) {
				inUrl = inUrl.replace(" ", "%20");
			}
			return inUrl;
		}
		if (!hasSpace) {
			if (Patterns.WEB_URL.matcher(inUrl).matches()) {
				return URLUtil.guessUrl(inUrl);
			}
		}

		// FIXME: Is this the correct place to add to searches?
		// what if someone else calls this function?

		return URLUtil.composeSearchUrl(inUrl, mQuickSearch_Current, QUERY_PLACE_HOLDER);
	}

	protected static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile("(?i)" + // switch on case insensitive matching
			"(" + // begin group for schema
			"(?:http|https|file|rtsp):\\/\\/" + "|(?:inline|data|about|javascript):" + ")" + "(.*)");

	@Override
	protected boolean _onCreateOptionsMenu(Menu menu) {
		getSupportMenuInflater().inflate(R.menu.activity_browser, menu);
		return true;
	}

	@Override
	protected boolean _onOptionsItemSelected(MenuItem item) {
		onSearchRequested();
		return true;
	}

	@Override
	public void onContextMenuClosed(android.view.Menu menu) {
		// TODO Auto-generated method stub
		super.onContextMenuClosed(menu);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
		CordovaWebView webview = (CordovaWebView) v;
		WebView.HitTestResult result = webview.getHitTestResult();
		if (result == null) {
			return;
		}

		int type = result.getType();
		if (type == WebView.HitTestResult.UNKNOWN_TYPE) {
			Log.w(TAG, "We should not show context menu when nothing is touched");
			return;
		}
		if (type == WebView.HitTestResult.EDIT_TEXT_TYPE) {
			// let TextView handles context menu
			return;
		}

		// Note, http://b/issue?id=1106666 is requesting that
		// an inflated menu can be used again. This is not available
		// yet, so inflate each time (yuk!)
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.browsercontext, menu);

		// Show the correct menu group
		final String extra = result.getExtra();
		menu.setGroupVisible(R.id.IMAGE_MENU, type == WebView.HitTestResult.IMAGE_TYPE
				|| type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE);

		// Setup custom handling depending on the type
		switch (type) {
		case WebView.HitTestResult.IMAGE_TYPE:
			if (type == WebView.HitTestResult.IMAGE_TYPE) {
				menu.setHeaderTitle(extra);
			}
			menu.findItem(R.id.view_image_context_menu_id).setOnMenuItemClickListener(new OnMenuItemClickListener() {

				@Override
				public boolean onMenuItemClick(android.view.MenuItem item) {
					mWebview.loadUrl(extra);
					return true;
				}

			});
			menu.findItem(R.id.download_context_menu_id).setOnMenuItemClickListener(new OnMenuItemClickListener() {

				@Override
				public boolean onMenuItemClick(android.view.MenuItem item) {
					try {
						String path = saveImage(extra) ;
						DeviceUtil.toast(mContext, "保存路径：" + path) ;
					} catch (MalformedURLException e) {
						Logger.e(TAG, e.getLocalizedMessage()) ;
					} catch (IOException e) {
						Logger.e(TAG, e.getLocalizedMessage()) ;
					}
					return true;
				}
			});
			menu.findItem(R.id.set_wallpaper_context_menu_id).setOnMenuItemClickListener(new SetAsWallpaper(extra));
			menu.findItem(R.id.share_link_context_menu_id).setOnMenuItemClickListener(new OnMenuItemClickListener() {

				@Override
				public boolean onMenuItemClick(android.view.MenuItem item) {
					ShareCompat.IntentBuilder.from(getActivity()).setType("text/plain").setText(extra).startChooser();
					return true;
				}
			});
			menu.findItem(R.id.share_image_context_menu_id).setOnMenuItemClickListener(new OnMenuItemClickListener() {

				@Override
				public boolean onMenuItemClick(android.view.MenuItem item) {
					try {
						share(BitmapFactory.decodeStream(new URL(extra).openStream()));
					} catch (MalformedURLException e) {
						Logger.e(TAG, e.getLocalizedMessage());
					} catch (IOException e) {
						Logger.e(TAG, e.getLocalizedMessage());
					}
					return true;
				}
			});
			break;

		}
		// hideFakeTitleBar();
	}

	@Override
	public boolean onContextItemSelected(android.view.MenuItem item) {
		// TODO Auto-generated method stub
		// Message msg = new Message();
		// mWebview.requestFocusNodeHref(msg);
		// DeviceUtil.toast(this, "selected");
		return super.onContextItemSelected(item);
	}

	private class SetAsWallpaper extends Thread implements OnMenuItemClickListener, DialogInterface.OnCancelListener {
		private URL mUrl;
		private ProgressDialog mWallpaperProgress;
		private boolean mCanceled = false;

		public SetAsWallpaper(String url) {
			try {
				mUrl = new URL(url);
			} catch (MalformedURLException e) {
				mUrl = null;
			}
		}

		public void onCancel(DialogInterface dialog) {
			mCanceled = true;
		}

		public boolean onMenuItemClick(android.view.MenuItem item) {
			if (mUrl != null) {
				// The user may have tried to set a image with a large file size as their
				// background so it may take a few moments to perform the operation. Display
				// a progress spinner while it is working.
				mWallpaperProgress = new ProgressDialog(mContext);
				mWallpaperProgress.setIndeterminate(true);
				mWallpaperProgress.setMessage(getText(R.string.progress_dialog_setting_wallpaper));
				mWallpaperProgress.setCancelable(true);
				mWallpaperProgress.setOnCancelListener(this);
				mWallpaperProgress.show();
				start();
			}
			return true;
		}

		public void run() {
			Drawable oldWallpaper = WallpaperManager.getInstance(mContext).getDrawable();
			try {
				// TODO: This will cause the resource to be downloaded again, when we
				// should in most cases be able to grab it from the cache. To fix this
				// we should query WebCore to see if we can access a cached version and
				// instead open an input stream on that. This pattern could also be used
				// in the download manager where the same problem exists.
				InputStream inputstream = mUrl.openStream();
				if (inputstream != null) {
					setWallpaper(inputstream);
				}
			} catch (IOException e) {
				Log.e(TAG, "Unable to set new wallpaper");
				// Act as though the user canceled the operation so we try to
				// restore the old wallpaper.
				mCanceled = true;
			}

			if (mCanceled) {
				// Restore the old wallpaper if the user cancelled whilst we were setting
				// the new wallpaper.
				int width = oldWallpaper.getIntrinsicWidth();
				int height = oldWallpaper.getIntrinsicHeight();
				Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
				Canvas canvas = new Canvas(bm);
				oldWallpaper.setBounds(0, 0, width, height);
				oldWallpaper.draw(canvas);
				try {
					setWallpaper(bm);
				} catch (IOException e) {
					Log.e(TAG, "Unable to restore old wallpaper.");
				}
				mCanceled = false;
			}

			if (mWallpaperProgress.isShowing()) {
				mWallpaperProgress.dismiss();
			}
		}

	}

	private String saveImage(String url) throws MalformedURLException, IOException {
		Bitmap bmp = BitmapFactory.decodeStream(new URL(url).openStream());

		String fileName = v2c_file_path + System.currentTimeMillis() + ".png";

		FileOutputStream fos = new FileOutputStream(fileName);

		if (fos != null) {

			bmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
			fos.flush();
			fos.close();
		}
		return fileName;
	}

	/**
	 * 截屏方法
	 * 
	 * @return
	 * @throws IOException
	 */
	private Bitmap shot() throws IOException {
		View view = getWindow().getDecorView();
		Display display = this.getWindowManager().getDefaultDisplay();
		view.layout(0, 0, display.getWidth(), display.getHeight());
		view.setDrawingCacheEnabled(true);// 允许当前窗口保存缓存信息，这样getDrawingCache()方法才会返回一个Bitmap
		return Bitmap.createBitmap(view.getDrawingCache());

		// return FileUtil.savePic(mContext, bmp);
	}

	private String capture() throws IOException {
		Picture pic = mWebview.capturePicture();

		int width = pic.getWidth();

		int height = pic.getHeight();

		if (width > 0 && height > 0) {

			Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

			Canvas mCanvas = new Canvas(bmp);

			pic.draw(mCanvas);

			FileUtil.savePic(mContext, bmp);
		}
		return "";
	}

	@Override
	protected void activityDestory() {
		// if (mWebview != null) {
		// mWebview.destroyDrawingCache();
		// mWebview.destroy();
		// }
	}

	private void actionBarShow() {
		mIsActionbarShow = !mIsActionbarShow;
		if (mIsActionbarShow) {
			getSupportActionBar().show();
		} else {
			getSupportActionBar().hide();
		}
	}

	@Override
	public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setData(Uri.parse(url));
		startActivity(intent);
	}

	private void share(Bitmap bitmap) {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
		final byte[] picture = stream.toByteArray();

		if (bitmap != null && !bitmap.isRecycled()) {
			bitmap.recycle();
		}
		UMSnsService.share(this, picture, "", null);
	}

	@Override
	public boolean onNavigationItemSelected(int itemPosition, long itemId) {
		mQuickSearch_Current = DataFactory.SE_ITEM[itemPosition];
		return true;
	}

	@Override
	public void onLowMemory() {
		super.onLowMemory();
		if (mWebview != null) {
			mWebview.freeMemory();
		}
	}
}